﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Dynamic;
using System.Linq;
using System.Windows.Forms;
using ContractManager.BLL.Business;
using ContractManager.Common.Class;
using ContractManager.Common.FormBase;
using ContractManager.Entity;
using DevExpress.Utils;
using DevExpress.XtraBars;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraLayout;
using DevExpress.XtraLayout.Utils;
using Speed.Data;

namespace ContractManager.Lists.Forms
{
    public partial class FrmTestDynamic : XtraFormBase
    {
        #region "Private Variable"

        public int MasterId;
        public bool OnlyView;
        public bool SaveClose;
        public bool SaveNew;

        private LayoutControlItem _lastItem;
        private List<FieldTables> _list;
        private List<FieldTables> _listGrid;

        private LayoutControlItem LastItem
        {
            get { return _lastItem; }
        }

        #endregion

        #region "Form Construction"

        public FrmTestDynamic()
        {
            InitializeComponent();
        }

        #endregion

        #region "Private Method"

        private void BlankForm()
        {
            ResetControls();
        }

        private void CreateLayoutForms()
        {
            _list = ClsFieldTables.SelectAll();
            _listGrid = _list.Where(e => e.FieldTalbeType == 6).ToList();
            CreateControlDynamic(_list);
        }

        /// <summary>
        ///     Phương thức tạo điều khiển động
        /// </summary>
        /// <param name="list"></param>
        private void CreateControlDynamic(List<FieldTables> list)
        {
            List<GridView> listGrid = new List<GridView>();
            
            layoutControl.BeginUpdate();

            foreach (FieldTables field in list)
            {
                string controlName = field.FieldTableName;
                string controlDisplay = field.FieldTableDescription;

                string controlFormual = field.FieldTableFormula;
                string controlGridLayout = field.GridLayoutName;
                string parentValueMember = field.ParentValueMember;
                string displayMember = field.DisplayMember;
                string valueMember = field.ValueMember;
                string validateExpress = field.ValidateExpress;

                int typeId = Convert.ToInt32(field.FieldTalbeType);
                var item = new LayoutControlItem {Text = controlDisplay};

                switch (typeId)
                {
                    case 1: //TextEdit
                        var txtTextEdit = new TextEdit {Name = controlName};
                        txtTextEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtTextEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        
                        item.Control = txtTextEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;

                        break;
                    case 2: //Memo Edit
                        var txtMemoEdit = new MemoEdit();
                        txtMemoEdit.Name = controlName;
                        txtMemoEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtMemoEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        
                        item.Control = txtMemoEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    case 3: //CalcEdit
                        var txtCalcEdit = new CalcEdit {Name = controlName};
                        txtCalcEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtCalcEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        
                        txtCalcEdit.Properties.Mask.EditMask = @"n0";
                        txtCalcEdit.Properties.Mask.UseMaskAsDisplayFormat = true;
                        txtCalcEdit.StyleController = layoutControl;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        
                        item.Control = txtCalcEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    case 4: //DateTime
                        var txtDateEdit = new DateEdit {Name = controlName};
                        txtDateEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtDateEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        
                        txtDateEdit.Properties.CalendarTimeProperties.CloseUpKey = new KeyShortcut(Keys.F4);
                        txtDateEdit.Properties.CalendarTimeProperties.PopupBorderStyle = PopupBorderStyles.Default;
                        txtDateEdit.Properties.Mask.EditMask = @"dd/MM/yyyy";
                        txtDateEdit.Properties.Mask.UseMaskAsDisplayFormat = true;

                        txtDateEdit.StyleController = layoutControl;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        
                        item.Control = txtDateEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    case 5: //Lookup Edit
                        DataTable dvDropDown = ClsSourceData.GetControlDataBySourceId(field.SourceDataId, "");
                        var slupDropDown = new SearchLookUpEdit {Name = controlName};
                        slupDropDown.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        slupDropDown.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        slupDropDown.Properties.View.OptionsBehavior.AutoPopulateColumns = false;
                        slupDropDown.Properties.View.OptionsView.ColumnAutoWidth = false;

                        slupDropDown.Properties.DataSource = dvDropDown;
                        slupDropDown.Properties.DisplayMember = displayMember;
                        slupDropDown.Properties.ValueMember = valueMember;

                        slupDropDown.Properties.NullText = "";
                        slupDropDown.Properties.PopupFormWidth = 350;

                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);

                        item.Control = slupDropDown;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        if (!String.IsNullOrEmpty(controlGridLayout))
                        {
                            string fileLayout = ClsVariable.GetRestoreLayoutFullPath(controlGridLayout);
                            slupDropDown.Properties.View.RestoreLayoutFromXml(fileLayout, DevExpress.Utils.OptionsLayoutBase.FullLayout);
                        }
                        break;
                    case 6: //Grid
                        DataTable dvGrid = ClsSourceData.GetControlDataBySourceId(field.SourceDataId, "");
                        var grdDynamic = new GridControl {Name = controlName};
                        var gridStatusGridView = new
                            GridView();
                        grdDynamic.MainView = gridStatusGridView;
                        gridStatusGridView.Name = "grv" + controlName;
                        gridStatusGridView.GridControl = grdDynamic;
                        grdDynamic.ViewCollection.AddRange(new BaseView[]
                        {
                            gridStatusGridView
                        });
                        grdDynamic.DataSource = dvGrid;
                        
                        grdDynamic.ForceInitialize();
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        
                        item.Control = grdDynamic;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 50;
                        if (!String.IsNullOrEmpty(controlGridLayout))
                        {
                            string fileLayout = ClsVariable.GetRestoreLayoutFullPath(controlGridLayout);
                            gridStatusGridView.RestoreLayoutFromXml(fileLayout, DevExpress.Utils.OptionsLayoutBase.FullLayout);
                        }
                        listGrid.Add(gridStatusGridView);
                        break;
                }
            }

            layoutControl.BestFit();
            layoutControl.EndUpdate();
        }

        private ExpandoObject GetDynamicSqlValue(List<FieldTables> list)
        {
            dynamic ret = new ExpandoObject();
            var item =
                list.FirstOrDefault(e => e.FieldTableKeyField != null && String.Format("{0}", e.FieldTableKeyField).Length > 0);
            
            string keyField = String.Format("{0}",item.FieldTableKeyField);
            ((IDictionary<String, Object>)ret).Add(keyField, MasterId);
            foreach (FieldTables field in list)
            {
                string controlName = field.FieldTableName;
                 if (controlName.Equals(field.FieldTableKeyField)) continue;
                int typeId = Convert.ToInt32(field.FieldTalbeType);

                if (typeId == 1 || typeId == 2)
                {
                    string sret = GetTextValue(controlName, typeId);
                    ((IDictionary<String, Object>) ret).Add(controlName, sret);
                }
                else if (typeId == 3)
                {
                    decimal dret = GetNumberValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, dret);
                }
                else if (typeId == 4)
                {
                    DateTime? dtret = GetDateValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, dtret);
                }

                else if (typeId == 5)
                {
                    int? itret = GetLookupValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, itret);
                }
                else
                {
                    ((IDictionary<String, Object>) ret).Add(controlName, DBNull.Value);
                }
            }
            return ret;
        }

        private string GetTextValue(string controlName, int typeId)
        {
            string ret = "";
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                ret = typeId == 1
                    ? String.Format("{0}", ((TextEdit) ctrl).EditValue)
                    : (typeId == 2 ? String.Format("{0}", ((MemoEdit) ctrl).EditValue) : "");
            }
            return ret;
        }

        private decimal GetNumberValue(string controlName)
        {
            decimal ret = 0;
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                ret = ((CalcEdit) ctrl).Value;
            }
            return ret;
        }

        private DateTime? GetDateValue(string controlName)
        {
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                return (DateTime?) ((DateEdit) ctrl).EditValue;
            }
            return null;
        }

        private int? GetLookupValue(string controlName)
        {
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                return (int?) ((SearchLookUpEdit) ctrl).EditValue;
            }
            return null;
        }

        private bool ExistsControlName(string name)
        {
            //bool ret1;
            return layoutControl.Controls.Cast<Control>().Any(ctrl => ctrl.Name.Equals(name));
        }

        private Control GetControlByName(string controlName)
        {
            return this.layoutControl.Controls.Find(controlName, true).FirstOrDefault();
        }

        private void GetDetail()
        {
            DataTable data=new DataTable();
            if (data.Rows.Count > 0)
            {
                DataRow row = data.Rows[0];
                foreach (FieldTables field in _list)
                {
                    string controlName = field.FieldTableName;
                    int typeId = Convert.ToInt32(field.FieldTalbeType);
                    switch (typeId)
                    {
                        case 1: //TextEdit
                            TextEdit textEdit = GetControlByName(controlName) as TextEdit;
                            if (textEdit != null) textEdit.EditValue = row[controlName];
                            break;
                        case 2: //Memo Edit
                            MemoEdit memoEdit = GetControlByName(controlName) as MemoEdit;
                            if (memoEdit != null) memoEdit.EditValue = row[controlName];
                            break;
                        case 3: //CalcEdit
                            CalcEdit calcEdit = GetControlByName(controlName) as CalcEdit;
                            if (calcEdit != null) calcEdit.EditValue = row[controlName];
                            break;
                        case 4: //DateTime
                            DateEdit dateEdit = GetControlByName(controlName) as DateEdit;
                            if (dateEdit != null) dateEdit.EditValue = row[controlName];
                            break;
                        case 5: //Lookup Edit
                            SearchLookUpEdit lookupEdit = GetControlByName(controlName) as SearchLookUpEdit;
                            if (lookupEdit != null) lookupEdit.EditValue = row[controlName];
                            break;
                        case 6: //Grid

                            break;
                    }
                }
            }
            
        }

        private void DoSave()
        {
            dynamic data = GetDynamicSqlValue(_list);
            try
            {
                if (MasterId > 0)
                {
                    ClsDynamic.UpdateObject(this.TableName, this.FieldNameId, data,data, _listGrid,0);
                }
                else
                {
                    ClsDynamic.InsertObject(this.TableName, this.FieldNameId, data,data, _listGrid,0,"");
                }
                
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message);
            }
            
        }

        private void DoDelete()
        {
        }

        #endregion

        #region "Form Event"

        private void FrmFieldTableDetailLoad(object sender, EventArgs e)
        {
            Sys.ConnectionString =
                @"Data Source =(local)\SQL2012; Initial Catalog =ERP.Hungnd; User Id =sa; Password =sql2012;";
            Sys.CommandTimeout = 1000;
            Sys.ProviderType = EnumDbProviderType.SqlServer;
            ClsVariable.Db = Sys.NewDb();
            CreateLayoutForms();
            BlankForm();
            if (!String.IsNullOrEmpty(FormXtraLayoutTemplate))
            {
                string fileLayout = ClsVariable.GetRestoreLayoutFullPath(FormXtraLayoutTemplate);
                layoutControl.RestoreLayoutFromXml(fileLayout);
            }
            if (MasterId > 0) GetDetail();
            btnSaveNew.Enabled = !OnlyView;
            btnSave.Enabled = !OnlyView;
            btnSaveClose.Enabled = !OnlyView;
            btnDelete.Enabled = !OnlyView;
            btnDesign.Enabled = !OnlyView;
        }

        #endregion

        #region "Toolbar Event"

        private void TbMenuItemClick(object sender, ItemClickEventArgs e)
        {
            switch (e.Item.Name)
            {
                case "btnSave":
                    DoSave();
                    break;
                case "btnSaveNew": //Lưu và thêm mới
                    SaveNew = true;
                    SaveClose = false;
                    DoSave();
                    break;
                case "btnSaveClose": //Lưu và đóng
                    SaveClose = true;
                    SaveNew = false;
                    DoSave();
                    break;
                case "btnDelete":
                    DoDelete();
                    break;
                case "btnDesign":
                    break;
                case "btnRefresh": //Nạp lại danh mục
                    break;
                case "btnHistory": //History
                    break;
                case "btnClose":
                    Close();
                    break;
            }
        }

        #endregion
    }
}